<?php

/**
 * ECSHOP 支付宝插件
 * ============================================================================
 * * 版权所有 2005-2012 上海商派网络科技有限公司，并保留所有权利。
 * 网站地址: http://www.ecshop.com；
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和
 * 使用；不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * $Author: douqinghua $
 * $Id: alipay.php 17217 2011-01-19 06:29:08Z douqinghua $
 */

if (!defined('IN_ECS'))
{
    die('Hacking attempt');
}

$payment_lang = ROOT_PATH . 'languages/' .$GLOBALS['_CFG']['lang']. '/payment/alipay.php';

if (file_exists($payment_lang))
{
    global $_LANG;

    include_once($payment_lang);
}

/* 模块的基本信息 */
if (isset($set_modules) && $set_modules == TRUE)
{
    $i = isset($modules) ? count($modules) : 0;

    /* 代码 */
    $modules[$i]['code']    = basename(__FILE__, '.php');

    /* 描述对应的语言项 */
    $modules[$i]['desc']    = 'alipay_desc';

    /* 是否支持货到付款 */
    $modules[$i]['is_cod']  = '0';

    /* 是否支持在线支付 */
    $modules[$i]['is_online']  = '1';

    /* 作者 */
    $modules[$i]['author']  = 'ECSHOP TEAM';

    /* 网址 */
    $modules[$i]['website'] = 'http://www.alipay.com';

    /* 版本号 */
    $modules[$i]['version'] = '1.0.2';

    /* 配置信息 */
    $modules[$i]['config']  = array(
        array('name' => 'alipay_account',           'type' => 'text',   'value' => ''),
        array('name' => 'alipay_key',               'type' => 'text',   'value' => ''),
        array('name' => 'alipay_partner',           'type' => 'text',   'value' => ''),
        array('name' => 'alipay_pay_method',        'type' => 'select', 'value' => '')
    );

    return;
}

/**
 * 类
 */
class alipay
{

    /**
     * 构造函数
     *
     * @access  public
     * @param
     *
     * @return void
     */
    function alipay()
    {
    }

    function __construct()
    {
        $this->alipay();
    }

    /**
     * 生成支付代码
     * @param   array   $order      订单信息
     * @param   array   $payment    支付方式信息
     * @param   array   $type       1为按钮2为支付链接
     */
    function get_code($pay, $payment,$type = 1)
    {
        if (!defined('EC_CHARSET'))
        {
            $charset = 'utf-8';
        }
        else
        {
            $charset = EC_CHARSET;
        }
        //服务器异步通知页面路径

        $notify_url = 'http://' . $_SERVER['SERVER_NAME'] . '/mobile/pay_return_y.php';

        //页面跳转同步通知页面路径
        $call_back_url = 'http://' . $_SERVER['SERVER_NAME'] . '/mobile/pay_return.php';
        //卖家支付宝帐户
        $seller_email =$payment['alipay_account'];
        //商户订单号
        $out_trade_no = $pay['order_sn'] . $pay['log_id'];
        //订单名称
        $subject = $pay['order_sn'];
        //付款金额
        $total_fee = $pay['order_amount'];
        //操作中断返回地址
        $merchant_url = 'http://' . $_SERVER['SERVER_NAME'] . '/mobile/index.php';


        //请求业务参数详细
        $req_data = '<direct_trade_create_req><notify_url>' . $notify_url . '</notify_url><call_back_url>' . $call_back_url . '</call_back_url><seller_account_name>' . $seller_email . '</seller_account_name><out_trade_no>' . $out_trade_no . '</out_trade_no><subject>' . $subject . '</subject><total_fee>' . $total_fee . '</total_fee><merchant_url>' . $merchant_url . '</merchant_url></direct_trade_create_req>';
        //必填

        /************************************************************/

        //构造要请求的参数数组，无需改动
        $para_token = array(
                "service"        => "alipay.wap.trade.create.direct",
                "partner"        => $payment['alipay_partner'],
                "sec_id"         => 'MD5',
                "format"         => 'xml',
                "v"              => '2.0',
                "req_id"         => date('Ymdhis'),
                "req_data"       => $req_data,
                "_input_charset" => $charset
        );

        //建立请求
        $html_text = $this->buildRequestHttp($para_token,$payment['alipay_key']);
        //URLDECODE返回的信息
        $html_text = urldecode($html_text);
        //解析远程模拟提交后返回的信息
        $para_html_text = $this->parseResponse($html_text);
        //获取request_token
        $request_token = $para_html_text['request_token'];
        /**************************根据授权码token调用交易接口alipay.wap.auth.authAndExecute**************************/
        //业务详细
        $req_data = '<auth_and_execute_req><request_token>' . $request_token . '</request_token></auth_and_execute_req>';
        $parameter = array(
            'service'           => "alipay.wap.auth.authAndExecute",
            'partner'           => $payment['alipay_partner'],
            'sec_id'            =>'MD5',
            "format"            => 'xml',
            "v"                 => '2.0',
            "req_id"            => date('Ymdhis'),
            "req_data"          => $req_data,//业务参数
            '_input_charset'    => $charset,
        );
        $para = $this->buildRequestPara($parameter,$payment['alipay_key']);
        foreach ($para as $key => $value) {
            $code=$code.$key.'='.$value.'&';
        }
        if ($type == 1) {
            $button = '<a href="http://wappaygw.alipay.com/service/rest.htm?'.$code.'"   id="pay" >付款</a>';
        }
        else{
              $button = 'http://wappaygw.alipay.com/service/rest.htm?'.$code;
        }
        return $button;
    }

    /**
     * 生成要请求给支付宝的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组
     */
    function buildRequestPara($para_temp,$key) {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = paraFilter($para_temp);
        //对待签名参数数组排序
        $para_sort = argSort($para_filter);
        //生成签名结果
        $prestr = createLinkstring($para_sort);
        $mysign = md5Sign($prestr, $key);
        //签名结果与签名方式加入请求提交参数组中
        $para_sort['sign'] = $mysign;
        if($para_sort['service'] != 'alipay.wap.trade.create.direct' && $para_sort['service'] != 'alipay.wap.auth.authAndExecute') {
            $para_sort['sign_type'] = strtoupper(trim($this->alipay_config['sign_type']));
        }
        return $para_sort;
    }

    /**
     * 建立请求，以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
     * @param $para_temp 请求参数数组
     * @return 支付宝处理结果
     */
    function buildRequestHttp($para_temp,$key) {
        $sResult = '';
        //待请求参数数组字符串
        $request_data = $this->buildRequestPara($para_temp,$key);

        //远程获取数据
        $sResult = getHttpResponsePOST('http://wappaygw.alipay.com/service/rest.htm?', getcwd().'\\cacert.pem',$request_data,trim(strtolower('utf-8')));
        return $sResult;
    }
    /**
     * 解析远程模拟提交后返回的信息
     * @param $str_text 要解析的字符串
     * @return 解析结果
     */
    function parseResponse($str_text) {
        //以“&”字符切割字符串
        $para_split = explode('&',$str_text);
        //把切割后的字符串数组变成变量与数值组合的数组
        foreach ($para_split as $item) {
            //获得第一个=字符的位置
            $nPos = strpos($item,'=');
            //获得字符串长度
            $nLen = strlen($item);
            //获得变量名
            $key = substr($item,0,$nPos);
            //获得数值
            $value = substr($item,$nPos+1,$nLen-$nPos-1);
            //放入数组中
            $para_text[$key] = $value;
        }
        
        if( ! empty ($para_text['res_data'])) {
            //token从res_data中解析出来（也就是说res_data中已经包含token的内容）
            $doc = new DOMDocument();
            $doc->loadXML($para_text['res_data']);
            $para_text['request_token'] = $doc->getElementsByTagName( "request_token" )->item(0)->nodeValue;
        }
        
        return $para_text;
    }
    // /**
    //  * 响应操作
    //  */
    // function respond()
    // {
    //     if (!empty($_POST))
    //     {
    //         foreach($_POST as $key => $data)
    //         {
    //             $_GET[$key] = $data;
    //         }
    //     }
    //     $payment  = get_payment($_GET['code']);
    //     $seller_email = rawurldecode($_GET['seller_email']);
    //     $order_sn = str_replace($_GET['subject'], '', $_GET['out_trade_no']);
    //     $order_sn = trim($order_sn);

    //     /* 检查数字签名是否正确 */
    //     ksort($_GET);
    //     reset($_GET);

    //     $sign = '';
    //     foreach ($_GET AS $key=>$val)
    //     {
    //         if ($key != 'sign' && $key != 'sign_type' && $key != 'code')
    //         {
    //             $sign .= "$key=$val&";
    //         }
    //     }

    //     $sign = substr($sign, 0, -1) . $payment['alipay_key'];
    //     //$sign = substr($sign, 0, -1) . ALIPAY_AUTH;
    //     if (md5($sign) != $_GET['sign'])
    //     {
    //         return false;
    //     }

    //     /* 检查支付的金额是否相符 */
    //     if (!check_money($order_sn, $_GET['total_fee']))
    //     {
    //         return false;
    //     }

    //     if ($_GET['trade_status'] == 'WAIT_SELLER_SEND_GOODS')
    //     {
    //         /* 改变订单状态 */
    //         order_paid($order_sn, 2);

    //         return true;
    //     }
    //     elseif ($_GET['trade_status'] == 'TRADE_FINISHED')
    //     {
    //         /* 改变订单状态 */
    //         order_paid($order_sn);

    //         return true;
    //     }
    //     elseif ($_GET['trade_status'] == 'TRADE_SUCCESS')
    //     {
    //         /* 改变订单状态 */
    //         order_paid($order_sn, 2);

    //         return true;
    //     }
    //     else
    //     {
    //         return false;
    //     }
    // }
}

//引用函数 

/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function paraFilter($para) {
    $para_filter = array();
    while (list ($key, $val) = each ($para)) {
        if($key == "sign" || $key == "sign_type" || $val == "")continue;
        else    $para_filter[$key] = $para[$key];
    }
    return $para_filter;
}
/**
 * 对数组排序
 * @param $para 排序前的数组
 * return 排序后的数组
 */
function argSort($para) {
    ksort($para);
    reset($para);
    return $para;
}
/**
 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstring($para) {
    $arg  = "";
    while (list ($key, $val) = each ($para)) {
        $arg.=$key."=".$val."&";
    }
    //去掉最后一个&字符
    $arg = substr($arg,0,count($arg)-2);
    
    //如果存在转义字符，那么去掉转义
    if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
    
    return $arg;
}


/**
 * 签名字符串
 * @param $prestr 需要签名的字符串
 * @param $key 私钥
 * return 签名结果
 */
function md5Sign($prestr, $key) {
    $prestr = $prestr . $key;
    return md5($prestr);
}

/**
 * 远程获取数据，POST模式
 * 注意：
 * 1.使用Crul需要修改服务器中php.ini文件的设置，找到php_curl.dll去掉前面的";"就行了
 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效，目前默认路径是：getcwd().'\\cacert.pem'
 * @param $url 指定URL完整路径地址
 * @param $cacert_url 指定当前工作目录绝对路径
 * @param $para 请求的数据
 * @param $input_charset 编码格式。默认值：空值
 * return 远程输出的数据
 */
function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = '') {

    if (trim($input_charset) != '') {
        $url = $url."_input_charset=".$input_charset;
    }
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
    curl_setopt($curl, CURLOPT_CAINFO,$cacert_url);//证书地址
    curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
    curl_setopt($curl,CURLOPT_POST,true); // post传输数据
    curl_setopt($curl,CURLOPT_POSTFIELDS,$para);// post传输数据
    $responseText = curl_exec($curl);
    //var_dump( curl_error($curl) );//如果执行curl过程中出现异常，可打开此开关，以便查看异常内容
    curl_close($curl);
    
    return $responseText;
}













?>